Skip to content

feat: collection likes management#1730

Merged
gaspergrom merged 4 commits intomainfrom
feat/collection-likes-management
Mar 10, 2026
Merged

feat: collection likes management#1730
gaspergrom merged 4 commits intomainfrom
feat/collection-likes-management

Conversation

@gaspergrom
Copy link
Collaborator

No description provided.

Signed-off-by: Gašper Grom <gasper.grom@gmail.com>
Signed-off-by: Gašper Grom <gasper.grom@gmail.com>
@gaspergrom gaspergrom self-assigned this Mar 9, 2026
Copilot AI review requested due to automatic review settings March 9, 2026 07:44
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds backend and shared-type support for “collection likes” (like/unlike, listing liked collections, and exposing like counts on collections), plus extends project insights typing/API responses.

Changes:

  • Add /api/collection/like GET/POST/DELETE endpoints and a CollectionLikeRepository for persistence.
  • Include likeCount in collection types and populate it in public collection queries/details.
  • Add project insights multi-fetch endpoint (/api/project/insights) and normalize insights responses (isLF, achievements).

Reviewed changes

Copilot reviewed 16 out of 16 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
frontend/types/project.ts Extends ProjectInsights types and introduces achievement type.
frontend/types/collection.ts Adds optional likeCount to collections.
frontend/setup/caching.ts Disables caching for like endpoints and mutating API methods.
frontend/server/utils/common.ts Adds getAuthUsername helper for deriving usernames from OIDC sub.
frontend/server/repo/communityCollection.repo.ts Joins owner info + adds likeCount aggregation for public collection queries/details.
frontend/server/repo/collectionLike.repo.ts New repository implementing like/unlike and listing liked collections.
frontend/server/middleware/jwt-auth.ts Protects /api/collection/like via JWT middleware.
frontend/server/api/project/insights.get.ts New endpoint to fetch insights for multiple projects and normalize response.
frontend/server/api/project/[slug]/insights.get.ts Normalizes single-project insights response (isLF, achievements).
frontend/server/api/collection/like/index.post.ts New endpoint to like a collection.
frontend/server/api/collection/like/index.get.ts New endpoint to list liked collections (paginated).
frontend/server/api/collection/like/index.delete.ts New endpoint to unlike a collection.
frontend/server/api/collection/community/my.get.ts Switches username derivation to getAuthUsername.
frontend/server/api/collection/community/index.post.ts Switches username derivation to getAuthUsername.
frontend/server/api/collection/community/[id].put.ts Switches username derivation to getAuthUsername.
frontend/server/api/collection/community/[id].delete.ts Switches username derivation to getAuthUsername.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +98 to +117
export interface ProjectInsightsAchievement {
leaderboardType: string;
rank: number;
totalCount: number;
}

export interface ProjectInsights {
id: string;
name: string;
slug: string;
logoUrl: string;
isLF: number;
contributorCount: number;
organizationCount: number;
softwareValue: number;
contributorDependencyCount: number;
contributorDependencyPercentage: number;
organizationDependencyCount: number;
organizationDependencyPercentage: number;
achievements: [string, number, number][];
Copy link

Copilot AI Mar 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ProjectInsightsAchievement is introduced but ProjectInsights.achievements is still typed as a tuple array, and ProjectInsights.isLF is still number even though the API endpoints now return isLF as a boolean and map achievements into {leaderboardType, rank, totalCount} objects. This makes the shared type misleading for API consumers and will cause type drift.

Consider splitting the types into a Tinybird/raw shape (e.g. ProjectInsightsTinybird with isLF: number and tuple achievements) and an API/client shape (e.g. ProjectInsights with isLF: boolean and achievements: ProjectInsightsAchievement[]), and update the endpoints to use the raw type for fetchFromTinybird and the mapped type for responses.

Copilot uses AI. Check for mistakes.
Comment on lines +43 to +56
const response = await fetchFromTinybird<ProjectInsights[]>('/v0/pipes/project_insights.json', {
slugs: slugs.length > 0 ? slugs : undefined,
ids: ids.length > 0 ? ids : undefined,
});

return response.data.map((project) => ({
...project,
isLF: !!project.isLF,
achievements:
project.achievements?.map(([leaderboardType, rank, totalCount]) => ({
leaderboardType,
rank,
totalCount,
})) ?? [],
Copy link

Copilot AI Mar 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This handler maps isLF from a number to a boolean and converts achievements tuples into objects, but it still uses the shared ProjectInsights type for the Tinybird response. To keep type safety and avoid confusing consumers, use a raw/Tinybird type for fetchFromTinybird and explicitly type the returned payload as the mapped API shape (with isLF: boolean and structured achievements).

Copilot uses AI. Check for mistakes.
Comment on lines +18 to +48
totalCount,
}),
) ?? [],
};
Copy link

Copilot AI Mar 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This endpoint returns a transformed shape (isLF boolean + structured achievements) but it fetches Tinybird data typed as ProjectInsights[] (which currently models isLF as number and achievements as tuples). Please align the types by introducing a Tinybird/raw type for the fetch and a separate API response type for the mapped return value, then type the handler accordingly.

Copilot uses AI. Check for mistakes.
@gaspergrom gaspergrom removed the request for review from epipav March 9, 2026 10:22
Copy link
Collaborator

@joanagmaia joanagmaia left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, @gaspergrom can you just address the typing issues raised by cursor bot review?

@gaspergrom gaspergrom merged commit e3ce674 into main Mar 10, 2026
8 of 9 checks passed
@gaspergrom gaspergrom deleted the feat/collection-likes-management branch March 10, 2026 08:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants